<?php

namespace App\Common\Lib\Hyperf;

use App\Common as com;
use Hyperf\Context;
use Psr\Http\Message\ServerRequestInterface;
use Hyperf\HttpMessage\Uri\Uri;
use Hyperf\HttpMessage\Stream\SwooleStream;
use Hyperf\HttpServer\Request as HttpServerRequest;
use Hyperf\HttpMessage\Server\Request as Psr7Request;
use Hyperf\HttpServer\Contract\RequestInterface;

class Request extends com\Lib\LibBase {

	/**
	 * 修改QueryParams
	 * @param array $newQueryParams
	 * @param ServerRequestInterface|null $request
	 * @return void
	 */
	public static function withQueryParams( array $newQueryParams, ServerRequestInterface $request = null ):void {
		// ...
		$request = $request ?? Context\Context::get( ServerRequestInterface::class );
//		if( $request === null ){
//			$request = self::newMessageRequest();
//		}
		//
		$serverRequest = $request->withQueryParams( $newQueryParams );
		Context\Context::set( ServerRequestInterface::class, $serverRequest );
		// 销毁旧数据
		Context\Context::set( 'http.request.parsedData', null );
	}

	/**
	 * 修改QueryParams
	 * @param string $newMethod
	 * @param ServerRequestInterface|null $request
	 * @return void
	 */
	public static function withMethod( string $newMethod, ServerRequestInterface $request = null ):void {
		// ...
		$request = $request ?? Context\Context::get( ServerRequestInterface::class );
		//
		$serverRequest = $request->withMethod( $newMethod );
		Context\Context::set( ServerRequestInterface::class, $serverRequest );
		// 销毁旧数据
		Context\Context::set( 'http.request.parsedData', null );
	}

	/**
	 * 获取http Request
	 * @return RequestInterface|null
	 */
	public static function getRequestOrNull():?RequestInterface {
		return Context\Context::get( RequestInterface::class );
	}

	/**
	 * 获取http Request
	 * @return RequestInterface
	 */
	public static function getRequestOrFail():RequestInterface {
		$request = Context\Context::get( RequestInterface::class );
		if( $request === null ){
			throw com\Lib\Err\Exception::makeOfNew( 'Get Request Interface Lose', com\Lib\Err\Code::$sysDataNotExist );
		}
		return $request;
	}

	/**
	 * 初始化http Request
	 * @param string $method 请求方式 [get] [post]
	 * @param string $path 请求路径
	 * @param array $param 参数数组
	 * ················· [可空](array)    $param['query']    说明：AAAAA
	 * ················· [可空](array)    $param['headers']    说明：AAAAA
	 * ················· [可空](array)    $param['form_params']    说明：AAAAA
	 * ················· [可空](array)    $param['json']    说明：AAAAA
	 * @return RequestInterface
	 */
	public static function initRequest( string $method, string $path = '', array $param = [] ):RequestInterface {
		//
		$request = self::getRequestOrNull();
		if( $request !== null ){
			return $request;
		}
		//
		if( Context\Context::get( ServerRequestInterface::class ) === null ){
			// 注入新的
			Context\Context::set( ServerRequestInterface::class, self::newMessageRequest( $method, $path, $param ) );
		}
		//
		$request = new HttpServerRequest();
		// 注入
		Context\Context::set( RequestInterface::class, $request );
		//
		return $request;
	}

	/**
	 * 初始化http Request->get
	 * @param string $path 请求路径
	 * @param array $param 参数数组
	 * ················· [可空](array)    $param['query']    说明：AAAAA
	 * ················· [可空](array)    $param['headers']    说明：AAAAA
	 * ················· [可空](array)    $param['form_params']    说明：AAAAA
	 * ················· [可空](array)    $param['json']    说明：AAAAA
	 * @return RequestInterface
	 */
	public static function initRequestOfGet( string $path = '', array $param = [] ):RequestInterface {
		return self::initRequest( 'get', $path, $param );
	}

	/**
	 * 初始化http Request->post
	 * @param string $path 请求路径
	 * @param array $param 参数数组
	 * ················· [可空](array)    $param['query']    说明：AAAAA
	 * ················· [可空](array)    $param['headers']    说明：AAAAA
	 * ················· [可空](array)    $param['form_params']    说明：AAAAA
	 * ················· [可空](array)    $param['json']    说明：AAAAA
	 * @return RequestInterface
	 */
	public static function initRequestOfPost( string $path = '', array $param = [] ):RequestInterface {
		return self::initRequest( 'post', $path, $param );
	}


	/**
	 * 初始化PSR标准Request
	 * @param string $method 请求方式 [get] [post]
	 * @param string $path 请求路径
	 * @param array $param 参数数组
	 * ················· [可空](array)    $param['query']    说明：AAAAA
	 * ················· [可空](array)    $param['headers']    说明：AAAAA
	 * ················· [可空](array)    $param['form_params']    说明：AAAAA
	 * ················· [可空](array)    $param['json']    说明：AAAAA
	 * @return Psr7Request
	 */
	private static function newMessageRequest( string $method, string $path = '', array $param = [] ):Psr7Request {
		$query = $param['query'] ?? [];
		$headers = $param['headers'] ?? [];
		$params = $param['form_params'] ?? [];
		$json = $param['json'] ?? [];
		$data = $params;

		$uri = ( new Uri() )->withPath( $path )->withQuery( http_build_query( $query ) );

		$content = http_build_query( $params );
		if( $method == 'POST' && data_get( $headers, 'Content-Type' ) == 'application/json' ){
			$content = json_encode( $json, JSON_UNESCAPED_UNICODE );
			$data = $json;
		}

		$body = new SwooleStream( $content );

		$request = new Psr7Request( $method, $uri, $headers, $body );
		$request = $request->withQueryParams( $query )->withParsedBody( $data );
		return $request;
	}


	/**
	 * 获取客户端ip地址
	 * @param RequestInterface|null $request [null]冻获取
	 * @return string|null
	 */
	public static function getIp( RequestInterface $request = null ):?string {
		if( $request === null ){
			$request = Context\Context::get( ServerRequestInterface::class );
			// $request = self::getRequestOrNull();
			if( $request === null ){
				return null;
			}
		}
		//
		$headers = $request->getHeaders();
		//
		if( isset( $headers['http_x_real_ip'] ) ){ // nginx 代理模式下，获取客户端真实IP
			return $headers['http_x_real_ip'][0];
		}else if( isset( $headers['http_client_ip'] ) ){ // 客户端的ip
			return $headers['http_client_ip'][0];
		}else if( isset( $headers['http_x_forwarded_for'] ) ){ // 浏览当前页面的用户计算机的网关
			$arr = explode( ',', $headers['http_x_forwarded_for'][0] );
			$pos = array_search( 'unknown', $arr );
			if( false !== $pos ) unset( $arr[$pos] );
			return trim( $arr[0] );
		}else if( isset( $headers['remote_addr'] ) ){
			return $headers['remote_addr'][0]; // 浏览当前页面的用户计算机的ip地址
		}
		// 特殊处理
		if( isset( $headers['x-real-ip'] ) ){ // 客户端的ip
			return $headers['x-real-ip'][0];
		}else if( isset( $headers['x-forwarded-for'] ) ){ // 浏览当前页面的用户计算机的网关
			$arr = explode( ',', $headers['x-forwarded-for'][0] );
			$pos = array_search( 'unknown', $arr );
			if( false !== $pos ) unset( $arr[$pos] );
			return trim( $arr[0] );
		}else if( isset( $headers['remote-host'] ) ){
			return $headers['remote-host'][0]; // 浏览当前页面的用户计算机的ip地址
		}else{
			return null;
		}
	}

}